<template>
<div class="wrapper" v-show="bReady">
    <header class="main-header" v-if="header && !iframe && aspect != 'fullscreen'">
        <nav class="navbar navbar-static-top" role="navigation">
            <div class="channel-title">{{title}}</div>
            <div class="navbar-custom-menu pull-left">
                <ul class="nav navbar-nav">
                    <li v-if="back">
                        <a :href="square"><i class="fa fa-chevron-left"></i> 广场</a>
                    </li>
                </ul>
            </div>
        </nav>
    </header>
    <div class="content-wrapper">
        <section :class="['content', {'no-padding': (iframe||!(share || showPtzTab)||aspect == 'fullscreen')}]">
            <div class="player-wrapper">
                <div class="play-area" @mousemove="resetActiveTimer" @touchstart="resetActiveTimer">
                     <LivePlayer :videoUrl="videoUrl" :waterMark="osd"
                        :hideBigPlayButton="!!serverInfo.HideBigPlayButton || hideBigPlayButton" :muted="muted" :hasaudio="hasAudio"
                        :fluent="fluent" :stretch="stretch" :autoplay="autoplay" :controls="controls" :showCameraButton="snap" :showCustomButton="custom"
                        :poster="poster" :aspect="aspect" live :alt="alt" :debug="debug"
                        @media_info="onMediaInfo" @error="onError" @message="$message" @fullscreen="onFullscreenChange"
                        v-loading="bLoading" :loading.sync="bLoading" :element-loading-text="loadingText" element-loading-background="#000"
                        :style="aspect == 'fullscreen' ? 'width: 100% !important;height: 100% !important;position: fixed !important;':''">
                        <div class="ptz-block" v-show="showPtzPanel">
                            <div class="ptz-cell ptz-up" @mousedown.prevent="ptzControl('up', $event)" @touchstart.prevent="ptzControl('up', $event)" title="上">
                                <i class="fa fa-chevron-up"></i>
                            </div>
                            <div class="ptz-cell ptz-left" @mousedown.prevent="ptzControl('left', $event)" @touchstart.prevent="ptzControl('left', $event)" title="左">
                                <i class="fa fa-chevron-left"></i>
                            </div>
                            <div class="ptz-cell ptz-right" @mousedown.prevent="ptzControl('right', $event)" @touchstart.prevent="ptzControl('right', $event)" title="右">
                                <i class="fa fa-chevron-right"></i>
                            </div>
                            <div class="ptz-cell ptz-down" @mousedown.prevent="ptzControl('down', $event)" @touchstart.prevent="ptzControl('down', $event)" title="下">
                                <i class="fa fa-chevron-down"></i>
                            </div>
                            <div class="ptz-cell ptz-center" title="云台控制">
                                <i class="fa fa-arrows"></i>
                            </div>
                            <div class="ptz-cell ptz-plus" @mousedown.prevent="ptzControl('zoomin', $event)" @touchstart.prevent="ptzControl('zoomin', $event)" title="放大">
                                <i class="fa fa-plus-circle"></i>
                            </div>
                            <div class="ptz-cell ptz-talk" @mousedown.prevent="talkStart" @touchstart.prevent="talkStart" v-if="showTalk">
                                <i class="fa fa-microphone"></i>
                            </div>
                            <div class="ptz-cell ptz-minus" @mousedown.prevent="ptzControl('zoomout', $event)" @touchstart.prevent="ptzControl('zoomout', $event)" title="缩小">
                                <i class="fa fa-minus-circle"></i>
                            </div>
                        </div>
                    </LivePlayer>
                </div>
                <div class="demo-area text-center" v-if="isDemoUser(serverInfo, userInfo) && !bOutHevcTip">
                    <br>
                    提示: 演示系统限制匿名登录播放时间, 若需测试长时间播放, 请<a target="_blank" href="//www.liveqing.com/docs/download/LiveNVR.html">下载使用</a>
                </div>
                <div class="tip-area text-center text-red" v-if="bOutHevcTip">
                    <br>
                    提示: 正在播放 H265 FLV 直出流, 确保浏览器版本较新, 并且开启硬件加速
                </div>
                <div class="share-area" v-if="!iframe && aspect != 'fullscreen' && (share || showPtzTab)">
                    <br>
                    <div class="nav-tabs-custom">
                        <ul class="nav nav-tabs">
                            <li v-show="share" :class="{active: share}">
                                <a href="#tab-share-link" data-toggle="tab"><i class="fa fa-share"> 分享</i></a>
                            </li>
                            <li v-show="showPtzTab" :class="{active: !share}">
                                <a href="#tab-ptz" data-toggle="tab"><i class="fa fa-arrows"> 云台控制</i></a>
                            </li>
                            <li v-if="tools && this.channel && !isMobile() && !isIE() && userInfo && hasAnyRole(serverInfo, userInfo, '超级管理员')">
                                <el-radio-group v-model="protocol" size="small" @change="changeProtocol">
                                    <el-radio-button label="FLV" v-if="flvSupported()"></el-radio-button>
                                    <el-radio-button label="WS_FLV" v-if="flvSupported()"></el-radio-button>
                                    <el-radio-button label="WEBRTC" v-if="rtcSupported()"></el-radio-button>
                                    <el-radio-button label="HLS"></el-radio-button>
                                    <el-radio-button label="RTMP"></el-radio-button>
                                </el-radio-group>
                            </li>
                            <li v-if="tools && userInfo && hasAnyRole(serverInfo, userInfo, '管理员') && videoUrl && errorNum == '200'" class="hidden-xs pull-right">
                                <button type="button" :class="['btn', 'btn-sm', {'btn-primary': !bRecording, 'btn-danger': bRecording}]" @click.prevent="toggleRecord()">
                                    <i :class="['fa', {'fa-save': !bRecording, 'fa-stop': bRecording}]"></i>
                                    {{bRecording? '停止录像' : '实时录像'}}
                                </button>
                            </li>
                        </ul>
                        <div class="tab-content">
                            <div :class="{'tab-pane': true, active: share}" id="tab-share-link">
                                <div class="form-horizontal" autocomplete="off">
                                    <div class="form-group" v-if="link && userInfo && hasAnyRole(serverInfo, userInfo, '超级管理员')">
                                        <label for="input-share-link" class="control-label col-sm-2">
                                            <a :href="shareUrl" target="_blank">分享链接</a>
                                        </label>
                                        <div class="col-sm-10">
                                            <div class="input-group">
                                                <input type="text" class="form-control" readonly="readonly" :value="shareUrl">
                                                <span class="input-group-btn">
                                                    <button type="button" class="btn btn-default" v-clipboard="shareUrl" title="点击拷贝" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"><i class="fa fa-copy"></i></button>
                                                </span>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="form-group" v-if="link && videoUrl && userInfo && hasAnyRole(serverInfo, userInfo, '超级管理员') && !isDemoUser(serverInfo, userInfo)">
                                        <label for="input-stream-link" class="control-label col-sm-2">流地址</label>
                                        <div class="col-sm-10">
                                            <div class="input-group">
                                                <input type="text" class="form-control" readonly="readonly" :value="videoUrl">
                                                <span class="input-group-btn">
                                                    <button type="button" class="btn btn-default" v-clipboard="videoUrl" title="点击拷贝" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"><i class="fa fa-copy"></i></button>
                                                </span>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="form-group" v-if="link && userInfo && hasAnyRole(serverInfo, userInfo, '超级管理员')">
                                        <label for="iframe" class="control-label col-sm-2">iframe</label>
                                        <div class="col-sm-10">
                                            <div class="input-group">
                                                <input type="text" class="form-control" readonly="readonly" :value="$iframe(iframeLink, 640, 360)">
                                                <span class="input-group-btn">
                                                    <button type="button" class="btn btn-default" v-clipboard="$iframe(iframeLink, 640, 360)" title="点击拷贝" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"><i class="fa fa-copy"></i></button>
                                                </span>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="form-group" v-if="qrcode">
                                        <label for="qrcode" class="control-label col-sm-2">扫码直播</label>
                                        <div class="col-sm-10">
                                            <Qrcode :value="shareUrl" tag="img" :options="{size: 150}"></Qrcode>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div :class="{'tab-pane': true, active:!share}" id="tab-ptz">
                                <div class="form-group">
                                    <div class="ptz-block-tab">
                                        <el-progress class="mic-level-bar" :percentage="level" :text-inside="true" v-if="ws"></el-progress>
                                        <div class="ptz-cell ptz-up" command="up" @mousedown.prevent="ptzControl('up', $event)" @touchstart.prevent="ptzControl('up', $event)" title="上">
                                            <i class="fa fa-chevron-up"></i>
                                        </div>
                                        <div class="ptz-cell ptz-left" command="left" @mousedown.prevent="ptzControl('left', $event)" @touchstart.prevent="ptzControl('left', $event)" title="左">
                                            <i class="fa fa-chevron-left"></i>
                                        </div>
                                        <div class="ptz-cell ptz-center" title="云台控制">
                                            <i class="fa fa-microphone" title="按住喊话" @mousedown.prevent="talkStart" @touchstart.prevent="talkStart" v-if="showTalk"></i>
                                        </div>
                                        <div class="ptz-cell ptz-right" command="right" @mousedown.prevent="ptzControl('right', $event)" @touchstart.prevent="ptzControl('right', $event)" title="右">
                                            <i class="fa fa-chevron-right"></i>
                                        </div>
                                        <div class="ptz-cell ptz-down" command="down" @mousedown.prevent="ptzControl('down', $event)" @touchstart.prevent="ptzControl('down', $event)" title="下">
                                            <i class="fa fa-chevron-down"></i>
                                        </div>
                                        <div class="ptz-cell ptz-zoomin" command="zoomin" @mousedown.prevent="ptzControl('zoomin', $event)" @touchstart.prevent="ptzControl('zoomin', $event)" title="放大">
                                            <i class="fa fa-plus"></i>
                                        </div>
                                        <div class="ptz-cell ptz-zoomout" command="zoomout" @mousedown.prevent="ptzControl('zoomout', $event)" @touchstart.prevent="ptzControl('zoomout', $event)" title="缩小">
                                            <i class="fa fa-minus"></i>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </section>
    </div>
    <footer class="main-footer text-center" v-if="footer && !iframe && aspect != 'fullscreen' && (share || showPtzTab)">
        <span v-if="serverInfo.CopyrightText" v-html="serverInfo.CopyrightText"></span>
        <span v-else>
            Copyright © 2021 <a href="//www.liveqing.com" target="_blank">www.liveqing.com</a> All rights reserved.
        </span>
    </footer>
    <resize-observer @notify="handleResize" />
</div>
</template>

<script>
import "font-awesome/css/font-awesome.css"
import "bootstrap/dist/css/bootstrap.css"
import "admin-lte/dist/css/skins/skin-blue.css"
import "vue-resize/dist/vue-resize.css"
import "assets/styles/AdminLTE-custom.less"
import "assets/styles/custom.less"

import "bootstrap/dist/js/bootstrap.min.js"
import "admin-lte/dist/js/adminlte.min.js"
import "jquery-ui/ui/widgets/draggable"

import Vue from "vue"
import { mapState, mapActions } from "vuex"
// import moment from "moment"

import ElementUI from "element-ui"
import "assets/styles/element-custom.scss"
Vue.use(ElementUI);

import VueClipboards from "vue-clipboards"
Vue.use(VueClipboards);

import VueResize from 'vue-resize'
Vue.use(VueResize);

Vue.prototype.$updateQueryString = (uri, key, value) => {
    var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
    var separator = uri.indexOf('?') !== -1 ? "&" : "?";
    if (uri.match(re)) {
        return uri.replace(re, '$1' + key + "=" + value + '$2');
    } else {
        return uri + separator + key + "=" + value;
    }
}
Vue.prototype.$getQueryString = (name, defVal = "") => {
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
    var r = window.location.search.substr(1).match(reg);
    if (r != null) {
        return decodeURIComponent(r[2]);
    }
    return defVal;
}
Vue.prototype.$removeQueryString = (url, ...parameters) => {
    //prefer to use l.search if you have a location/link object
    for(var parameter of parameters) {
        var urlparts = url.split('?');
        if (urlparts.length >= 2) {
            var prefix = encodeURIComponent(parameter) + '=';
            var pars = urlparts[1].split(/[&;]/g);

            //reverse iteration as may be destructive
            for (var i = pars.length; i-- > 0;) {
                //idiom for string.startsWith
                if (pars[i].lastIndexOf(prefix, 0) !== -1) {
                    pars.splice(i, 1);
                }
            }
            url = urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : '');
        }
    }
    return url;
}
Vue.prototype.$iframe = (link, w, h) => {
    return `<iframe src="${link}" width="${w}" height="${h}" allowfullscreen allow="autoplay; fullscreen"></iframe>`;
}
Vue.prototype.isMobile = () => {
    return videojs.browser.IS_IOS || videojs.browser.IS_ANDROID;
}
Vue.prototype.flvSupported = () => {
    return videojs.browser.IE_VERSION || (flvjs.getFeatureList() && flvjs.getFeatureList().mseLiveFlvPlayback);
}
Vue.prototype.rtcSupported = () => {
    return !!window.RTCPeerConnection;
}
Vue.prototype.isIE = () => {
    return videojs.browser.IE_VERSION;
}
Vue.prototype.canTalk = () => {
  return location.protocol.indexOf("https") == 0 || location.hostname === 'localhost' || location.hostname === '127.0.0.1';
}
Vue.prototype.hasAnyRole = (serverInfo, userInfo, ...roles) => {
    if (serverInfo && (serverInfo.APIAuth === false || !serverInfo.LiveStreamAuth) && !userInfo) {
        return true;
    }
    var userRoles = [];
    if (userInfo) {
        userRoles = userInfo.roles || [];
    }
    var checked = false;
    for(var role of (roles||[])) {
        if (!role || userRoles.some(ur => (ur == role || ur == '超级管理员'))) {
            checked = true;
            break;
        }
    }
    return checked;
}
Vue.prototype.isDemoUser = (serverInfo, userInfo) => {
  if (serverInfo && userInfo && userInfo.name === serverInfo.DemoUser) return true;
  return false;
}

import Qrcode from "@xkeshi/vue-qrcode"
import LivePlayer from "@liveqing/liveplayer"
import $ from "jquery"
import "@penggy/jquery.nicescroll"
$.ajaxSetup({ cache: false });
export default {
    components: { LivePlayer, Qrcode },
    data() {
        return {
            errorNum: "",
            errorString: "",
            deviceType: "",
            videoUrl: "",
            poster: "",
            bLoading: false,
            title: "",
            timer: 0,
            channel: "",
            protocol: "",
            shareUrl: "",
            ptz: false,
            talk: false,
            fluent: true,
            stretch: false,
            iframe: false,
            autoplay: true,
            controls: true,
            snap: true,
            custom: true,
            aspect: "",
            alt: "无信号",
            loadingText: "加载中...",
            muted: true,
            hasAudio: false,
            hasTalk: false,
            debug: false,
            nice: null,
            share: false,
            header: true,
            footer: true,
            back: false,
            link: true,
            qrcode: true,
            tools: true,
            hideBigPlayButton: false,
            menu: "",
            online: "",
            online_dropdown: false,
            square: "/#/index/icons",
            osd: "",
            search: true,
            q: "",
            token: "",
            fullpath: true,
            otherParams: "",
            bRecording: false,
            bReady: false,
            mediaInfo: null,
            bOutHevcTip: false,
            fullscreen: false,
            activeTimer: null,
            bControls: false,
            recorder: null,
            ws: null,
            level: 0,
            activeInterval: 0,
        };
    },
    beforeDestroy() {
        if (this.timer) {
            clearInterval(this.timer);
            this.timer = 0;
        }
        this.videoUrl = "";
        this.ctrlStop();
        $(document).off("mouseup touchend", this.mouseUp);
    },
    created() {
        this.iframe = this.$getQueryString("iframe", "no") == "yes";
        this.header = this.$getQueryString("header", "yes") == "yes";
        this.footer = this.$getQueryString("footer", "yes") == "yes";
        this.back = this.$getQueryString("back", "no") == "yes";
        this.link = this.$getQueryString("link", "yes") == "yes";
        this.qrcode = this.$getQueryString("qrcode", "yes") == "yes";
        this.tools = this.$getQueryString("tools", "yes") == "yes";
        this.muted = this.$getQueryString("muted", "yes") == "yes";
        this.autoplay = this.$getQueryString("autoplay", "yes") == "yes";
        this.controls = this.$getQueryString("controls", "yes") == "yes";
        this.snap = this.$getQueryString("snap", "yes") == "yes";
        this.custom = this.$getQueryString("custom", "yes") == "yes";
        this.fluent = this.$getQueryString("fluent", "yes") == "yes";
        this.stretch = this.$getQueryString("stretch", "no") == "yes";
        this.debug = this.$getQueryString("debug") == "yes";
        this.hideBigPlayButton = this.$getQueryString("hide_big_play_button", "no") == "yes";
        this.aspect = this.$getQueryString("aspect").replace("x", ":");
        if (this.iframe && !this.aspect) {
            this.aspect = 'fullscreen';
        }
        this.alt = this.$getQueryString("alt", "无信号");
        this.osd = this.$getQueryString("osd", "");
        this.loadingText = this.$getQueryString("loading_text", "加载中...");
        this.token = this.$getQueryString("token", "");
        this.fullpath = this.$getQueryString("fullpath", "yes") == "yes";
    },
    async mounted() {
        await this.getServerInfo();
        var payload = {};
        if(this.token) {
            payload["token"] = this.token;
        }
        await this.getUserInfo(payload);
        if(this.userInfo) {
            this.ptz = this.$getQueryString("ptz", "yes") == "yes";
            this.talk = this.$getQueryString("talk", "yes") == "yes";
        } else {
            this.ptz = this.$getQueryString("ptz", "no") == "yes";
            this.talk = this.$getQueryString("talk", "no") == "yes";
        }
        document.title = this.serverInfo.LogoText || "LiveNVR";
        this.bReady = true;
        this.menu = this.$getQueryString("menu", "");
        this.q = this.$getQueryString("q", "");
        this.online = this.$getQueryString("online", "");
        this.online_dropdown = this.$getQueryString("online_dropdown", "");
        this.search = this.$getQueryString("search", "yes") == "yes";
        var defShare = this.serverInfo.ShowShare === false ? "no" : "yes";
        this.share = this.$getQueryString("share", defShare) == "yes";
        this.protocol = String(this.$getQueryString("protocol", this.serverInfo.PreferStreamFmt||"")).toUpperCase();
        if (this.protocol == "WS-FLV") {
            this.protocol = "WS_FLV";
        }
        if(this.protocol == "RTSP") {
            this.protocol = "";
        } else if(this.protocol == "WEBRTC" && !this.rtcSupported()) {
            this.protocol = "";
        } else if(this.protocol == "FLV" && this.isIE()) {
            this.protocol = "";
        } else if((this.protocol == "FLV" || this.protocol == "WS_FLV") && !this.flvSupported()) {
            this.protocol = "HLS";
        }
        this.shareUrl = this.$removeQueryString(location.href, "q", "back", "online");
        this.otherParams = this.getOtherParams(["q", "iframe", "aspect", "autoplay", "controls", "snap", "custom", "ptz", "share", "fluent", "fullpath",
            "stretch", "alt", "type", "starttime", "endtime", "channel", "protocol", "muted", "talk", "debug", "hide_big_play_button",
            "search", "menu", "online", "online_dropdown", "header", "footer", "back", "link", "qrcode", "tools", "loading_text", "osd"]);
        this.initsquare(defShare == "yes");
        $(document).ajaxError((evt, xhr, opts, ex) => {
            if (xhr.status == 401) {
                if (this.serverInfo.DemoUser) {
                    location.href = `/login?r=${encodeURIComponent(location.href)}`;
                } else {
                    if (this.iframe || this.aspect == 'fullscreen') {
                        console.log("登录认证过期");
                    } else {
                        location.href = `/login?r=${encodeURIComponent(location.href)}`;
                        // this.$message({
                        //     type: 'error',
                        //     message: "登录认证过期",
                        // })
                    }
                }
                return false;
            } else if (xhr.status) {
                let msg = xhr.responseText || "网络请求失败";
                if (xhr.status == 404) {
                    msg = "请求服务不存在或已停止";
                } else if (xhr.status == 504) {
                    msg = "Gateway Timeout";
                }
                try {
                    msg = JSON.parse(msg);
                } catch (error) {}
                if (this.iframe || this.aspect == 'fullscreen') {
                    console.log(msg);
                } else {
                    this.$message({
                        type: 'error',
                        message: msg,
                    })
                }
            } else {
                console.log(`ajax error: ${xhr.status} ${xhr.responseText}`);
            }
        }).on("mouseup touchend", this.mouseUp).ready(() => {
            this.$nextTick(() => {
                $("body").layout("fix");
                this.fixHover();
                this.initNiceScroll();
            })
        }).on('shown.bs.modal', () => {
            this.removeNiceScroll();
        }).on('hidden.bs.modal', () => {
            this.initNiceScroll();
        });
        $(".ptz-block").draggable({
            handle: '.ptz-center',
            // cancel: ".ptz-cell",
            containment: '.play-area .video-js, .play-area .qplayer-canvas, .play-area .qplayer-h5-video',
            delay: 100
        }).on("mouseover", ".ptz-center", () => {
            if(!this.isMobile() && this.bControls) {
                this.activeInterval = 5000;
                this.resetActiveTimer();
            }
        });
        this.channel = this.$getQueryString("channel") || "";
        if (!this.protocol) {
            this.protocol = "HLS";
            if (this.flvSupported()) {
                this.protocol = this.isIE() ? "WS_FLV" : "FLV";
            } else if(this.rtcSupported()) {
                this.protocol = "WEBRTC";
            }
        }

        // this.shareUrl = this.$updateQueryString(location.href, "protocol", this.protocol);
        if (!this.channel) {
            await this.getChannel();
        }
        if (this.channel) {
            this.getChannelStream();
        }
    },
    computed: {
        ...mapState(["serverInfo", "userInfo"]),
        showTalk() {
            return this.talk && this.canTalk() && this.hasTalk && this.videoUrl && this.errorNum == "200"
                && this.hasAnyRole(this.serverInfo, this.userInfo, '管理员', '操作员');
        },
        showPtzPanel() {
            return this.ptz && (this.deviceType == "ONVIF" || this.deviceType.endsWith('SDK') || this.deviceType == "ISUP") && this.videoUrl && this.errorNum == "200"
                && !this.isMobile() && this.hasAnyRole(this.serverInfo, this.userInfo, '管理员', '操作员') && this.bControls;
        },
        showPtzTab() {
            return this.ptz && (this.deviceType == "ONVIF" || this.deviceType.endsWith('SDK') || this.deviceType == "ISUP") && this.videoUrl && this.errorNum == "200"
                && this.isMobile() && this.hasAnyRole(this.serverInfo, this.userInfo, '管理员', '操作员');
        },
        iframeLink() {
            return this.$updateQueryString(this.$updateQueryString(this.shareUrl, "stretch", "yes"), "iframe", "yes");
        },
    },
    methods: {
        ...mapActions([ "getServerInfo", "getUserInfo" ]),
        initNiceScroll() {
            if(!this.isIE() && !this.isMobile() && !this.nice) {
                this.nice = $('body').niceScroll({
                    zindex: 999999,
                    cursorwidth: "10px",
                    cursoropacitymax: 0.5,
                    preservenativescrolling: false,
                    enablekeyboard: false,
                });
            }
        },
        removeNiceScroll() {
            if (this.nice) {
                this.nice.remove();
                this.nice = null;
            }
        },
        fixHover() {
            if (videojs.browser.IS_IOS || videojs.browser.IS_ANDROID) {
                for (var sheetI = document.styleSheets.length - 1; sheetI >= 0; sheetI--) {
                    var sheet = document.styleSheets[sheetI];
                    if (sheet.cssRules) {
                        for (var ruleI = sheet.cssRules.length - 1; ruleI >= 0; ruleI--) {
                            var rule = sheet.cssRules[ruleI];
                            if (rule.selectorText) {
                                rule.selectorText = rule.selectorText.replace(":hover", ":active");
                                rule.selectorText = rule.selectorText.replace(":focus", ":active");
                            }
                        }
                    }
                }
            }
        },
        // thisYear() {
        //     return moment().format("YYYY");
        // },
        getOtherParams(without) {
            var url = location.search;
            var theRequest = "";
            if (url.indexOf("?") != -1) {
                var str = url.substr(1);
                var strs = str.split("&");
                for (var i = 0; i < strs.length; i++) {
                    if (without.indexOf(strs[i].split("=")[0]) == -1) {
                        if (theRequest == "") {
                            theRequest = strs[i]
                        } else {
                            theRequest += "&" + strs[i]
                        }
                    }
                }
            }
            return theRequest;
        },
        ptzControl(cmd, event) {
            $.get("/api/v1/ptzcontrol", {
                channel: this.channel,
                speed: 5,
                command: cmd,
                token: this.token,
            })
            $(event.target).closest('.ptz-cell').addClass("active");
        },
        ptzStop() {
            if ($(".ptz-cell.active:not(.ptz-talk)").length > 0) {
                $.get("/api/v1/ptzcontrol", {
                    channel: this.channel,
                    speed: 5,
                    command: "stop",
                    token: this.token,
                }).always(() => {
                    if(!this.isMobile() && this.bControls) {
                        this.activeInterval = 5000;
                        this.resetActiveTimer();
                    }
                })
                $(".ptz-cell.active:not(.ptz-talk)").removeClass("active");
            }
        },
        talkStart(e) {
            if(!this.ws) {
                this.ws = new WebSocket(this.wsTalkURL());
                this.ws.onopen = evt => {
                    console.log("ws talk open");
                }
                this.ws.onclose = evt => {
                    console.log("ws talk close");
                }
                this.ws.onerror = evt => {
                    console.log("ws talk error", evt);
                }
            } else if(this.serverInfo.TalkHold) {
                this.talkStop();
                return;
            }
            var $target = $(e.currentTarget);
            if(this.recorder) {
                $target.addClass("active");
                this.recorder.start();
                return;
            }
            LiveRecorder.get((rec, err) => {
                if(err) {
                    alert(err);
                    this.talkStop();
                    return
                }
                // this.$refs["player"].setMuted(true);
                $target.addClass("active");
                this.recorder = rec;
                this.recorder.start();
            }, {
                sampleBits: 16,
                sampleRate: 8000,
                pcmCallback: (pcm, level) => {
                    // binary to base64 string
                    var reader = new window.FileReader();
                    reader.onloadend = () => {
                        var base64 = reader.result;
                        var base64 = base64.split(',')[1];
                        if(this.ws && this.ws.readyState === WebSocket.OPEN) {
                            this.ws.send(base64);
                            this.level = level;
                        }
                    }
                    reader.readAsDataURL(pcm);
                }
            })
        },
        talkStop() {
            if(this.recorder) {
                // this.recorder.stop();
                this.recorder.destroy();
                this.recorder = null;
                $(this.$el).find(".fa-microphone.active, .ptz-talk.active").removeClass("active");
                // this.$refs["player"].setMuted(false);
            }
            if(this.ws) {
                this.ws.close();
                this.ws = null;
                if(!this.isMobile() && this.bControls) {
                    this.activeInterval = 5000;
                    this.resetActiveTimer();
                }
            }
            this.level = 0;
        },
        ctrlStop() {
            this.talkStop();
            this.ptzStop();
        },
        mouseUp() {
            if(!this.serverInfo.TalkHold) {
                this.talkStop();
            }
            this.ptzStop();
        },
        changeProtocol() {
            if(this.bOutHevcTip && !String(this.protocol).endsWith("FLV")) {
                this.bOutHevcTip = false;
            }
            this.shareUrl = this.$updateQueryString(this.$removeQueryString(location.href, "q", "back", "online"), "protocol", this.protocol);
            this.getChannelStream();
        },
        toggleRecord() {
            if(this.bRecording) {
                var recURL = `/api/v1/realtime/record/stop?channel=${this.channel}`;
                if(this.token) {
                    recURL += `&token=${this.token}`;
                }
                window.open(recURL, "_blank");
                this.bRecording = false;
            } else {
                $.get("/api/v1/realtime/record/start", {
                    channel: this.channel,
                    token: this.token,
                }).then(() => {
                    this.bRecording = true;
                })
            }
        },
        handleResize() {
            this.nice && this.nice.resize();
        },
        wsTalkURL() {
            var protocol = "ws:";
            if(location.protocol.startsWith("https")) {
                protocol = "wss:";
            }
            var talkURL = `${protocol}//${location.host}/api/v1/ws-talk?format=pcm&channel=${this.channel}`;
            if(this.token) {
                talkURL += `&token=${this.token}`;
            }
            return talkURL;
        },
        initsquare(defShare) {
            var p = "";
            if (this.iframe) {
                p = "iframe=yes";
            }
            if (this.aspect != "") {
                if (p == "") {
                    p = "aspect=" + this.aspect;
                } else {
                    p = p + "&aspect=" + this.aspect;
                }
            }
            if (this.share != defShare) {
                if (p == "") {
                    p = "share=no";
                } else {
                    p = p + "&share=no";
                }
            }
            if (!this.search) {
                if (p == "") {
                    p = "search=no";
                } else {
                    p = p + "&search=no";
                }
            }
            let ptz = this.$getQueryString("ptz", "");
            if (ptz) {
                if (p == "") {
                    p = "ptz=" + ptz;
                } else {
                    p = p + "&ptz=" + ptz;
                }
            }
            if (this.menu != "") {
                if (p == "") {
                    p = "menu=" + this.menu;
                } else {
                    p = p + "&menu=" + this.menu;
                }
            }
            if (p != "") {
                p = "?" + p;
            }
            var q = "";
            if (this.online) {
                if (q == "") {
                    q = "online=" + this.online;
                } else {
                    q = q + "&online=" + this.online;
                }
            }
            if (this.q != "") {
                if (q == "") {
                    q = "q=" + this.q;
                } else {
                    q = q + "&q=" + this.q;
                }
            }
            if (this.online_dropdown) {
                if (q == "") {
                    q = "online_dropdown=" + this.online_dropdown;
                } else {
                    q = q + "&online_dropdown=" + this.online_dropdown;
                }
            }
            if (q != "") {
                q = "?" + q;
            }
            this.square = `/${p}#/index/icons${q}`;
        },
        getChannel() {
            this.name = this.$getQueryString("name") || "";
            return new Promise((resolve, reject) => {
                if(!this.name) {
                    resolve({});
                    return
                }
                $.get("/api/v1/getchannels", {
                    q: decodeURI(this.name),
                    start: 0,
                    limit: 1,
                    token: this.token,
                }).then(data => {
                    try {
                        if ((data.LiveQing || data.NVR).Body.Channels.length > 0) {
                            this.channel = (data.LiveQing || data.NVR).Body.Channels[0].Channel + "" || "";
                        }
                    } catch (error) {
                        console.log(error);
                    }
                    resolve({});
                }).fail(() => {
                    resolve({});
                })
            })
        },
        getChannelStream(fg = true) {
            if(fg) {
                this.bLoading = true;
            }
            $.get("/api/v1/getchannelstream", {
                channel: this.channel,
                protocol: this.protocol,
                token: this.token,
                fullpath: this.fullpath,
            }).then(data => {
                this.errorNum = (data.LiveQing || data.NVR).Header.ErrorNum;
                this.errorString = (data.LiveQing || data.NVR).Header.ErrorString;
                this.hasAudio = (data.LiveQing || data.NVR).Body.AudioEnable;
                this.hasTalk = (data.LiveQing || data.NVR).Body.TalkEnable || false;
                this.bRecording = (data.LiveQing || data.NVR).Body.Recording;
                this.title = (data.LiveQing || data.NVR).Body.ChannelName;
                this.osd = this.osd || (data.LiveQing || data.NVR).Body.OSD;
                this.deviceType = String((data.LiveQing || data.NVR).Body.DeviceType).toUpperCase();
                if (this.protocol == "RTMP") {
                    this.poster = "";
                } else {
                    var snapURL = (data.LiveQing || data.NVR).Body.SnapURL || "";
                    if(snapURL && this.otherParams) {
                        if (snapURL.indexOf("?") == -1) {
                            snapURL += "?" + this.otherParams;
                        } else {
                            snapURL += "&" + this.otherParams;
                        }
                    }
                    this.poster = snapURL;
                }
                var _videoUrl = String((data.LiveQing || data.NVR).Body.URL).replace("{host}", location.hostname);
                if (this.errorNum != "200") {
                    console.log(`get channel[${this.channel}] stream res[${this.errorNum}] ${this.errorString}`);
                    if(_videoUrl) {
                        if(this.poster) {
                            this.hideBigPlayButton = true;
                            this.controls = false;
                        } else {
                            _videoUrl = "";
                        }
                    }
                }
                if(_videoUrl && this.otherParams) {
                    if (_videoUrl.indexOf("?") == -1) {
                        _videoUrl += "?" + this.otherParams;
                    } else {
                        _videoUrl += "&" + this.otherParams;
                    }
                }
                this.videoUrl = _videoUrl; // no need in next tick since player@2.6.9
                if(!_videoUrl || this.errorNum != "200") {
                    if(fg) {
                        this.bLoading = false;
                    }
                    if(this.timer) {
                        clearTimeout(this.timer);
                        this.timer = 0;
                    }
                    this.timer = setTimeout(() => {
                        this.getChannelStream(false);
                    }, 3000);
                    return;
                }
                if(this.timer) {
                    clearTimeout(this.timer);
                    this.timer = 0;
                }
            }).fail(() => {
                if(fg) {
                    this.$nextTick(() => {
                        this.bLoading = false;
                    })
                }
                if(this.timer) {
                    clearTimeout(this.timer);
                    this.timer = 0;
                }
                this.timer = setTimeout(() => {
                    this.getChannelStream(false);
                }, 3000);
            })
        },
        onMediaInfo(mi) {
            this.mediaInfo = mi;
        },
        onError(e) {
            if(e == 'MediaError' && this.mediaInfo && String(this.mediaInfo.videoCodec).startsWith("hvc")) {
                this.bOutHevcTip = true;
                console.log("提示: 正在播放 H265 FLV 直出流, 确保浏览器版本较新, 并且开启硬件加速");
            }
        },
        onFullscreenChange(fullscreen) {
            this.fullscreen = fullscreen;
            $(".play-area .ptz-block").css({
                top: "20px",
                right: "20px",
                left: "",
            });
        },
        resetActiveTimer() {
            this.bControls = true;
            if (this.activeTimer) {
                clearTimeout(this.activeTimer)
            }
            this.activeTimer = setTimeout(() => {
                this.activeInterval = 0;
                if ($(this.$el).find(".ptz-block .ptz-cell.active").length == 0) {
                    this.bControls = false;
                }
            }, this.activeInterval || 2000);
        },
    }
};
</script>

<style lang="less" scoped>
.main-header .navbar {
    /* Fix for IE */
    -webkit-transition: none;
    -o-transition: none;
    transition: none;
}

.skin-green .wrapper,
.skin-green .main-sidebar,
.skin-green .left-side {
    background-color: #ecf0f5 !important;
}

.channel-title {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    color: #fff;
    text-align: center;
    padding: 0 15px;
    font-size: 20px;
    line-height: 50px;
    font-weight: 700;
}

.content-wrapper {
    .content {
        & > .player-wrapper {
            margin: 0 auto;
        }
        &:not(.no-padding) > .player-wrapper {
            width: 75%;
        }
        &.no-padding > .player-wrapper {
            width: 100%;
        }
        @media (max-width: 719px) {
            &:not(.no-padding) > .player-wrapper {
                width: 100%;
            }
        }
    }
}

.osd-block {
    position: absolute;
    text-align: left;
    font-size: 1.75vw;
    background-color: #525a5e;
    padding:0.45vw;
    border-radius: 2px;
    opacity: 0.8;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

.ptz-block-tab {
  width: 150px;
  height: 210px;
  margin: 0 auto;
  text-align: center;
  position: relative;
  font-size: 24px;

    .ptz-cell {
        width: 50px;
        height: 50px;
        line-height: 50px;
        position: absolute;
    }

    .ptz-cell.active {
        color: #ccc;
        font-size: 26px;
    }

    .fa-microphone, .fa-microphone-slash {
        padding: 10px 13px;
        border-radius: 25px;
    }

    .fa-microphone.active {
        color: #fff;
    }

    .mic-level-bar {
        position: absolute;
        transform: rotate(-90deg);
        width: 100%;
        top: 70px;
        left: -80px;
    }

    .ptz-center {
        top: 50px;
        left: 50px;
        border-radius: 25px;
        background-color: #ccc;
    }

    .ptz-up {
        top: 0;
        left: 50px;
    }

    .ptz-left {
        top: 50px;
        left: 0;
    }

    .ptz-right {
        top: 50px;
        left: 100px;
    }

    .ptz-down {
        top: 100px;
        left: 50px;
    }

    .ptz-zoomin {
        top: 150px;
        left: 20px;
    }

    .ptz-talk {
        top: 150px;
        left: 50px;
    }

    .ptz-zoomout {
        top: 150px;
        left: 80px;
    }

    .ptz-up,
    .ptz-left,
    .ptz-right,
    .ptz-down,
    .ptz-zoomin,
    .ptz-talk,
    .ptz-zoomout {
        cursor: pointer;
    }
}

.ptz-block {
    position: absolute;
    z-index: 99999;
    width: 150px;
    height: 220px;
    right: 20px;
    top: 20px;
    text-align: center;
    font-size: 24px;
    background: fade(#eee, 0%);
    border-radius: 16px;
    overflow: hidden;
    color: #333;

    &:hover {
        background: fade(#eee, 60%);

        .ptz-cell {
            display: block;
        }
    }

    .ptz-cell {
        width: 50px;
        height: 50px;
        line-height: 50px;
        position: absolute;
        cursor: pointer;
        display: none;
    }

    .ptz-cell.active {
        color: #FFF;
        font-size: 26px;
    }

    .ptz-center {
        top: 60px;
        left: 50px;
        width: 50px;
        height: 50px;
        line-height: 50px;
        display: block;
        position: absolute;
        border-radius: 25px;
        background: fade(#ccc, 20%);
        cursor: move;

        i {
            color: fade(#000, 30%);
        }
    }

    .ptz-up {
        top: 10px;
        left: 50px;
    }

    .ptz-left {
        top: 60px;
        left: 0;
    }

    .ptz-right {
        top: 60px;
        left: 100px;
    }

    .ptz-down {
        top: 110px;
        left: 50px;
    }

    .ptz-plus {
        top: 160px;
        left: 15px;
    }

    .ptz-talk {
        top: 160px;
        left: 50px;
    }

    .ptz-minus {
        top: 160px;
        left: 85px;
    }

    .mic-level-bar {
        position: absolute;
        transform: rotate(-90deg);
        width: 100%;
        top: 70px;
        right: -80px;
    }
}
</style>
